package bancosys.tec.persist.span.fat;

import java.util.Collections;
import java.util.List;

import jmine.tec.annotations.Unmodifiable;
import jmine.tec.persist.PersistMessages;
import bancosys.tec.persist.persister.listener.AbstractPersisterListener;
import bancosys.tec.persist.span.SpanAwareBean;
import bancosys.tec.persist.span.SpanAwareBeanComparator;
import bancosys.tec.persist.validator.ValidationError;
import bancosys.tec.persist.validator.ValidationException;
import bancosys.tec.utils.date.Date;

/**
 * @created Mar 2, 2007
 * @author Rafael Volpato
 */
@Unmodifiable
public class FatSpanAwarePersisterListener extends AbstractPersisterListener<FatSpanAwareBean<?>> {

    /**
     * Executado antes do insert na base quente.
     * 
     * @param bean bean.
     * @param action action
     */
    @Override
    public void beforeInsert(FatSpanAwareBean<?> bean, Object action) {
        this.updateDataFimVigencias(bean);
    }

    /**
     * Executado antes do remove na base quente.
     * 
     * @param bean bean.
     */
    @Override
    public void beforeRemove(FatSpanAwareBean<?> bean) {
        this.updateDataFimVigencias(bean);
    }

    /**
     * Executado antes do update na base quente.
     * 
     * @param bean bean.
     * @param action action
     */
    @Override
    public void beforeUpdate(FatSpanAwareBean<?> bean, Object action) {
        this.updateDataFimVigencias(bean);
    }

    /**
     * Atualiza o campo dataFim de todas as vigências do bean.
     * 
     * @param fatBean o bean a ter as datas validadas.
     */
    @SuppressWarnings("unchecked")
    private void updateDataFimVigencias(FatSpanAwareBean fatBean) {

        List<? extends SpanAwareBean> vigencias = fatBean.getVigencias();

        if (!vigencias.isEmpty()) {

            Collections.sort(vigencias, new SpanAwareBeanComparator());

            SpanAwareBean lastSpan = null;
            Date startDate = null;
            Date lastDate = SpanAwareBean.DATA_FIM;
            for (int i = vigencias.size() - 1; i >= 0; i--) {
                SpanAwareBean span = vigencias.get(i);
                startDate = (Date) span.getDataInicio().clone();

                /* Validar a dataInicio */
                if ((lastSpan != null)
                        && ((lastSpan.getDataInicio().before(span.getDataInicio()) || lastSpan.getDataInicio().equals(span.getDataInicio())))) {
                    throw new ValidationException(new ValidationError(PersistMessages.VALIDATION_ERROR_INVALID_DATE.create(), fatBean));
                }

                /*
                 * Atualizar a dataFim se necessario, validar se existe alguma inconsistencia
                 */
                if (lastSpan == null) {
                    /* 'span' é a última vigência da lista, atualizar a dataFim */
                    span.setDataFim(lastDate); /* DATA_FIM */

                } else {
                    /* Se o 'span' atual for o penultimo, atualizar a dataFim se ela estiver inconsistente */
                    if (lastSpan.getDataFim().equals(SpanAwareBean.DATA_FIM) && span.getDataFim().equals(SpanAwareBean.DATA_FIM)) {
                        span.setDataFim(((Date) lastSpan.getDataInicio().clone()).addDays(-1));
                    }
                }

                lastDate = startDate.addDays(-1);
                lastSpan = span;
            }
        }
        Collections.reverse(vigencias);
    }
}
